package com.company.cloud.user.modules.app.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.company.cloud.captcha.modules.util.StringUtils;
import com.company.cloud.common.bean.LoginSimpleUserInfo;
import com.company.cloud.common.bean.LoginUserInfo;
import com.company.cloud.common.constant.BaseReturnEnum;
import com.company.cloud.common.exception.BusinessException;
import com.company.cloud.common.redis.service.RedisUtils;
import com.company.cloud.common.utils.PasswordUtils;
import com.company.cloud.user.constant.ErrorUserEnum;
import com.company.cloud.user.constant.UserStateEnum;
import com.company.cloud.user.modules.app.models.ThirdUserEntity;
import com.company.cloud.user.modules.app.models.User2ThirdModel;
import com.company.cloud.user.modules.app.service.UserLoginService;
import com.company.cloud.user.modules.app.utils.UserUtils;
import com.company.cloud.user.modules.base.entity.ThirdUserInfo;
import com.company.cloud.user.modules.base.entity.UserInfo;
import com.company.cloud.user.modules.base.entity.UserRoleInfo;
import com.company.cloud.user.modules.base.service.ThirdUserInfoService;
import com.company.cloud.user.modules.base.service.UserInfoService;
import com.company.cloud.user.modules.base.service.UserRoleInfoService;
import com.company.cloud.user.modules.cache.service.UserPermissionCacheService;
import com.company.common.server.config.cloud.ProjectConfig;
import com.company.common.server.constant.LoginThirdChannelEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

@Service
public class UserLoginServiceImpl implements UserLoginService {

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private UserRoleInfoService userRoleInfoService;

    @Autowired
    private ThirdUserInfoService thirdUserInfoService;

    @Autowired
    private ProjectConfig projectConfig;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private UserPermissionCacheService userPermissionCacheService;

    /**
     * 根据手机号获取用户
     */
    @Override
    public UserInfo getUserByMobile(String companyNo, String mobile) {
        UserInfo userInfo = userInfoService.getOne(new QueryWrapper<UserInfo>()
                .eq(projectConfig.isCompanyPattern(), "company_no", companyNo)
                .eq("mobile", mobile));
        if (userInfo == null) {
            throw new BusinessException(ErrorUserEnum.User_Info_Null);
        }
        if (!UserStateEnum.NORMAL.getCode().equals(userInfo.getUserState())) {
            throw new BusinessException(ErrorUserEnum.User_Info_Null);
        }
        return userInfo;
    }

    /**
     * 根据用户名获取用户
     */
    @Override
    public UserInfo getUserByUserName(String companyNo, String userName) {
        if (projectConfig.isCompanyPattern()) {
            if (StringUtils.isEmpty(companyNo)) {
                throw new BusinessException(BaseReturnEnum.PARAM_NULL);
            }
        }
        UserInfo userInfo = userInfoService.getOne(new QueryWrapper<UserInfo>()
                .eq(projectConfig.isCompanyPattern(), "company_no", companyNo)
                .eq("user_name", userName));
        if (userInfo == null) {
            throw new BusinessException(ErrorUserEnum.User_Info_Null);
        }
        if (!UserStateEnum.NORMAL.getCode().equals(userInfo.getUserState())) {
            throw new BusinessException(ErrorUserEnum.User_Info_Null);
        }
        return userInfo;
    }

    /**
     * 根据用户ID获取用户
     */
    @Override
    public UserInfo getUserById(Integer id) {
        UserInfo userInfo = userInfoService.getById(id);
        if (userInfo == null) {
            throw new BusinessException(ErrorUserEnum.User_Info_Null);
        }
        if (!UserStateEnum.NORMAL.getCode().equals(userInfo.getUserState())) {
            throw new BusinessException(ErrorUserEnum.User_Info_Null);
        }
        return userInfo;
    }

    /**
     * 根据手机号获取用户-注册
     */
    @Override
    public UserInfo getRegUserByMobile(String companyNo, String mobile) {
        UserInfo userInfo = userInfoService.getOne(new QueryWrapper<UserInfo>()
                .eq(projectConfig.isCompanyPattern(), "company_no", companyNo)
                .eq("mobile", mobile));
        if (userInfo == null) {
            return null;
        }
        if (!UserStateEnum.NORMAL.getCode().equals(userInfo.getUserState())) {
            throw new BusinessException(ErrorUserEnum.User_Info_Null);
        }
        return userInfo;
    }

    /**
     * 根据用户名获取用户-注册
     */
    @Override
    public UserInfo getRegUserByUserName(String companyNo, String userName) {
        UserInfo userInfo = userInfoService.getOne(new QueryWrapper<UserInfo>()
                .eq(projectConfig.isCompanyPattern(), "company_no", companyNo)
                .eq("user_name", userName));
        if (userInfo == null) {
            return null;
        }
        if (!UserStateEnum.NORMAL.getCode().equals(userInfo.getUserState())) {
            throw new BusinessException(ErrorUserEnum.User_Info_Null);
        }
        return userInfo;
    }

    /**
     * 根据用户ID获取用户-注册
     */
    @Override
    public UserInfo getRegUserById(Integer id) {
        UserInfo userInfo = userInfoService.getById(id);
        if (userInfo == null) {
            return null;
        }
        if (!UserStateEnum.NORMAL.getCode().equals(userInfo.getUserState())) {
            throw new BusinessException(ErrorUserEnum.User_Info_Null);
        }
        return userInfo;
    }

    /**
     * 用户名密码登录
     */
    @Override
    public UserInfo loginByUserName(String companyNo, String userName, String password) {
        UserInfo userInfo = this.getUserByUserName(companyNo, userName);
        if (!PasswordUtils.isCorrect(password, userInfo.getSalt(), userInfo.getPassword())) {
            throw new BusinessException(ErrorUserEnum.User_Password_Error);
        }
        return userInfo;
    }

    /**
     * 手机号密码登录
     */
    @Override
    public UserInfo loginByMobile(String companyNo, String mobile, String password) {
        UserInfo userInfo = this.getUserByMobile(companyNo, mobile);
        if (!PasswordUtils.isCorrect(password, userInfo.getSalt(), userInfo.getPassword())) {
            throw new BusinessException(ErrorUserEnum.User_Password_Error);
        }
        return userInfo;
    }


    /**
     * 根据第三方用户OpenId登录
     */
    @Override
    public User2ThirdModel loginByThird(String companyNo, LoginThirdChannelEnum channel, String openId, String ip, boolean isReg) {
        ThirdUserInfo thirdUser = thirdUserInfoService.getOne(new QueryWrapper<ThirdUserInfo>()
                .eq("channel_no", channel.getCode())
                .eq("open_id", openId));

        if (thirdUser == null) {
            thirdUser = new ThirdUserInfo();
            thirdUser.setCompanyNo(companyNo);
            thirdUser.setChannelNo(channel.getCode());
            thirdUser.setOpenId(openId);
            thirdUser.setUserId(-1);
            thirdUser.setCman(-1);
            thirdUser.setEman(-1);
            thirdUser.setCdt(LocalDateTime.now());
            thirdUser.setEdt(LocalDateTime.now());
            thirdUser.setCip(ip);
            thirdUser.setEip(ip);
            thirdUserInfoService.save(thirdUser);
        }

        UserInfo user = null;
        if (thirdUser.getUserId() > 0) {
            if (isReg) {
                user = this.getRegUserById(thirdUser.getUserId());
            } else {
                user = this.getUserById(thirdUser.getUserId());
            }
        }
        User2ThirdModel data = new User2ThirdModel();
        data.setThirdUser(thirdUser);
        data.setUser(user);
        return data;
    }


    /**
     * 登录
     */
    @Override
    public LoginUserInfo login(UserInfo userInfo) {
        List<UserRoleInfo> userRoles = userRoleInfoService.list(
                new QueryWrapper<UserRoleInfo>().eq("user_id", userInfo.getId()));
        LoginUserInfo user = UserUtils.loginUser2cache(userInfo, null, userRoles, projectConfig.isSSO(), redisUtils, null, null);
        return user;
    }

    /**
     * 登录
     */
    @Override
    public LoginUserInfo login(UserInfo userInfo, String token) {
        List<UserRoleInfo> userRoles = userRoleInfoService.list(
                new QueryWrapper<UserRoleInfo>().eq("user_id", userInfo.getId()));
        LoginUserInfo user = UserUtils.loginUser2cache(userInfo, null, userRoles, projectConfig.isSSO(), redisUtils, token, null);
        return user;
    }

    /**
     * 登录
     */
    @Override
    public LoginUserInfo login(UserInfo userInfo, ThirdUserInfo thirdUser, ThirdUserEntity thirdUserEntity) {
        List<UserRoleInfo> userRoles = null;
        if (userInfo != null) {
            userRoles = userRoleInfoService.list(
                    new QueryWrapper<UserRoleInfo>().eq("user_id", userInfo.getId()));
        }
        LoginUserInfo user = UserUtils.loginUser2cache(userInfo, thirdUser, userRoles, projectConfig.isSSO(), redisUtils, null, thirdUserEntity);
        return user;
    }

    /**
     * 登录
     */
    @Override
    public LoginUserInfo login(UserInfo userInfo, ThirdUserInfo thirdUser, String token, ThirdUserEntity thirdUserEntity) {
        List<UserRoleInfo> userRoles = null;
        if (userInfo != null) {
            userRoles = userRoleInfoService.list(
                    new QueryWrapper<UserRoleInfo>().eq("user_id", userInfo.getId()));
        }
        LoginUserInfo user = UserUtils.loginUser2cache(userInfo, thirdUser, userRoles, projectConfig.isSSO(), redisUtils, token, thirdUserEntity);
        return user;
    }

    /**
     * 登出
     */
    @Override
    public void logout(LoginSimpleUserInfo userInfo) {
        userPermissionCacheService.logoutUser(userInfo);
    }

    @Override
    public void updateThirdUserId(LoginThirdChannelEnum channel, String openId, Integer userId) {
        ThirdUserInfo thirdUser = thirdUserInfoService.getOne(new QueryWrapper<ThirdUserInfo>()
                .eq("channel_no", channel.getCode())
                .eq("open_id", openId));
        thirdUser.setUserId(userId);
        thirdUserInfoService.updateById(thirdUser);
    }

    @Override
    public void updateUserInfo(UserInfo userInfo) {
        userInfoService.updateById(userInfo);
    }

}
